package com.atguigu.controller;

import com.atguigu.bean.Book;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.PrintWriter;

/**SpringMVC如何获取请求带来的各种信息？
 * 方式一：默认方式
 *      直接给拦截方法的入参写一个参数 此参数名 和 请求参数名相同。这个变量会自动接收请求参数的值
 *          携带请求参数：有值
 *          不带请求参数：null值
 *
 * 方式二：使用3个注解
 *
 *      获取请求参数                  @RequestParam
 *      获取请求头中某个key的值        @RequestHeader
 *      获取某个cookie的值            @CookieValue
 * @author 伟哥
 * @date 2021-05-08 12:30
 */
@Controller
public class HelloController {
    /**
     * 测试环境搭建HelloWorld
     * @return
     */
    @RequestMapping("/hello")
    public String handle01(){
        System.out.println("handle01...");
        return "success";
    }

    /**
     * 默认方式，获取请求参数：
     *      在方法参数列表，填入 和 请求参数相同名称的 参数名，即可自动接收请求参数
     * @return
     */
    @RequestMapping("/handle02")
    public String handle02(String username){
        System.out.println("这个变量的值="+username);
        return "success";
    }

    /**注解：@RequestParam
     *      1）、在方法参数列表，填入一个参数用来接收请求参数
     *      2）、参数上加上此注解@RequestParam(value= "需要获取的参数名称")
     *
     *      【获取请求参数】，效果和默认方式，获取参数，相同。
     *
     *      @RequestParam("username")String parametersName
     *      parametersName = request.getParameter("username");
     *
     *      注意：
     *          此参数，默认要求，请求必须携带指定的参数，否则【报错】，
     *          将此注解的required设置为false，就不会报错，获取到null值
     *      属性：
     *          value：指定要获取请求参数的key
     *          required：调整这个参数是否，是必须携带的。默认true
     *          defaultValue：不携带参数，获取的默认值，默认是null，可以手动指定默认值。注意，手动指定默认值后，required属性会自动设置为false
     *
     *      区别：@RequestParam("user")
     *      区别：@PathVariable("user")    /book/{user = @PathVariable的}?user = @RequestParam的
     *
     * @param parametersName
     * @return
     */
    @RequestMapping("/handle03")
    public String handle03(@RequestParam(value = "username",required = false,defaultValue = "没有携带指定的参数")String parametersName){
        System.out.println("这个变量的值="+parametersName);
        return "success";
    }

    /**
     * 注解：@RequestHeader
     *      【获取请求头中某个key的值】
     *      1）、在方法参数列表，填入一个参数用来接收请求参数
     *      2）、参数上加上此注解@RequestHeader(value= "需要获取的请求头的key值")
     *
     *      以前获取请求头中key的方式：
     *          request.getHeader("User-Agent");
     *      现在：
     *      @RequestHeader(value = "User-Agent",defaultValue = "没有user-agent信息") String userAgent
     *          等同于userAgent = request.getHeader("User-Agent");
     *
     *
     *      注意：
     *         此参数，默认要求，请求必须携带指定的参数，否则【报错】，
     *          将此注解的required设置为false，就不会报错，获取到null值
     *      属性：
     *          value：指定要获取请求头中的key
     *          required：调整这个参数是否，是必须携带的。默认true
     *          defaultValue：不携带参数，获取的默认值，默认是null，可以手动指定默认值。注意，手动指定默认值后，required属性会自动设置为false
     *
     * @return
     */
    @RequestMapping("/handle04")
    public String handle04(@RequestHeader(value = "User-Agent",defaultValue = "没有user-agent信息") String userAgent){
        System.out.println("请求头中的信息userAgent："+userAgent);
        return "success";
    }

    /**注解：@CookieValue
     *      获取某个cookie的值
     *      1）、在方法参数列表，填入一个参数用来接收请求参数
     *      2）、参数上加上此注解@CookieValue(value= "需要获取Cookie中的key值")
     *
     *
     *      以前的获取某个cookie的值
     *      Cookie[] cookies = request.getCookies();
     *      for(Cookie cookie : cookies){
     *          if(cookie.getName.equals("JSESSIONID")){
     *              String value = cookie.getValue();
     *          )
     *      }
     *
     *      注意：
     *         此参数，默认要求，请求必须携带指定的参数，否则【报错】，
     *         将此注解的required设置为false，就不会报错，获取到null值
     *      属性：
     *          value：指定要获取请求头中的key
     *          required：调整这个参数是否，是必须携带的。默认true
     *          defaultValue：不携带参数，获取的默认值，默认是null，可以手动指定默认值。注意，手动指定默认值后，required属性会自动设置为false
     * @return
     */
    @RequestMapping("/handle05")
    public String handle05(@CookieValue(value = "JSESSIONID",defaultValue = "全部的cookie中，没有我们需要的JSEESIONID")String jId){
        System.out.println("cookie中的JESSIONID是："+jId);
        return "success";
    }

    /**
     * 三个注解【综合使用】
     */
    @RequestMapping("/handle06")
    public String handle06(@RequestParam(value = "username",required = false) String userName,
                           @RequestHeader(value = "User-Agent",required = false) String userAgent,
                           @CookieValue(value = "JSESSIONID",required = false) String jSessionId){
        System.out.println("携带的参数username是："+userName);
        System.out.println("请求头中的UserAgent是："+userAgent);
        System.out.println("cookies中的JSESSIONID是："+jSessionId);

        return "success";
    }


    /**自动封装javaBean（POJO）
     * 处理图书请求
     *  1）、入参，填入javabean类
     *  2）、SpringMVC会自动从request的请求参数中，尝试获取javabean中的属性，
     *      并将从request中获取到的值，封装进javabean类中。
     *
     * 如果我们的请求参数是一个POJO对象
     * SpringMVC会自动的为这个POJO对象进行赋值，怎么进行赋值呢？
     *      【原理】★★★
     *      1）、将POJO中的每一个属性（所以，提前创建好javaBean的类），从request请求参数中尝试获取出来，并封装进入。
     *      2）、还可以封装级联属性（属性的属性）
     *
     *      我们的入参Book，中有许多参数，bookName、author、price、stock、sales
     *      SpringMVC就会使用request.getParameter("bookName")、request.getParameter("author")。。
     *      SpringMVC获取到这些值，之后，将其封装进入参Book中
     *
     * 打印对象，控制台出现乱码！！！！
     * 【提交的数据可能有乱码】区分，是什么乱码：
     * 请求乱码：
     *      GET请求：
     *          改server.xml，位置tomcat/conf/server.xml
     *          1）、找到8080端口，所在的标签行
     *          <Connector port="8080" protocol="HTTP/1.1"
     *                connectionTimeout="20000"
     *                redirectPort="8443" />
     *          2）、加入属性 URIEncodings="UTF-8"
     *          <Connector URIEncodings="UTF-8" port="8080" protocol="HTTP/1.1"
     *                       connectionTimeout="20000"
     *                       redirectPort="8443" />
     *
     *      POST请求：
     *          在第一次获取请求参数之前设置request.setCharacterEncoding("UTF-8");
     *
     *          【可是，这是SpringMVC】自动装配，我们的代码无处可写，别着急。手写一个过滤器Filter
     *          不过这个Filter，SpringMVC已经考虑到了，自带了，我们不用写了，去web.xml配置一下即可
     *          这个Filter叫做org.springframework.web.filter.CharacterEncodingFilter
     *
     * 响应乱码：
     *      response.setContentType("text/html; charset=UTF-8");
     */
    @RequestMapping("/book")
    public String addBook(Book book){
        System.out.println("我要保存的图书："+book);
        return "success";
    }

    /**
     * 原生API：
     *  SpringMVC可以直接在参数上写原生API
     *      例如：
     *      HttpServletRequest
     *      HttpServletResponse
     *      HttpSession
     *
     *      java.security.Principal：【和HTTPS安全协议有关】
     *      Locale：国际化有关的区域信息
     *      InputStream 从哪来的？
     *          ServletInputStream inputStream = request.getInputStream();
     *      OutputStream 从哪来的的？
     *          ServletOutputStream outputStream = response.getOutputStream();
     *      Reader 字符流
     *          BufferedReader reader = request.getReader();
     *      Writer 字符流
     *          PrintWriter writer = response.getWriter();
     *
     */
    @RequestMapping("/handle07")
    public String handle07(HttpSession session, HttpServletRequest request, HttpServletResponse response){
        /*
        假设：
            现在我们需要给session中保存一些数据！
            那我们需要1个session对象啊，session对象在哪里？
                非常简单，直接在入参处，写上HttpSession

            那么，我还想像保存数据在请求中呢，那么request又怎么获取？
                非常简单，直接在入参处，写上HttpServletRequest

            以前使用session：
                request.getSession;
         */

        //1、数据保存在请求中
        request.setAttribute("reqParam","我是请求域中的数据");
        session.setAttribute("sessionParam","我是session域中的数据");
        //2、在success页面中，将数据取出来
        return "success";
    }
}
